////
// @file btreeTest.cc
// @brief
//
// @author ycm
// @email klgjok@163.com
//
#include "../catch.hpp"
#include <db/btree.h>
#include <vector>
#include <string>
#include <iostream>

using namespace bpt;

static unsigned char testBTreeBuffer[1000 * sizeof(BTreeNode)];
// 插入的value为int
static int testData[1000];

TEST_CASE("db/btree.h")
{
    BTree btree;
    btree.attach(testBTreeBuffer, sizeof(testBTreeBuffer));
    btree.clear();

    SECTION("attach")
    {
        REQUIRE(btree.getSize() == 0);
    }
    SECTION("detach")
    {
        btree.detach();
        REQUIRE(btree.getSize() == 0);
    }
    SECTION("insert")
    {
        for (int i=0; i<100; ++i) {
            testData[i] = i;
            btree.insert(i, &testData[i]);
            for (int j=0; j<=i; ++j) {
                auto result = static_cast<int*>(btree.search(j));
                REQUIRE(result != nullptr);
                REQUIRE(*result == j);
            }
        }
    }
    SECTION("single search")
    {
        for (int i=0; i<100; ++i) {
            testData[i] = i;
            btree.insert(i, &testData[i]);
        }
        for (int i=0; i<100; ++i) {
            auto result = static_cast<int*>(btree.search(i));
            REQUIRE(result != nullptr);
            REQUIRE(*result == i);
        }
        for (int i=100; i<200; ++i) {
            auto *result = static_cast<std::string*>(btree.search(i));
            REQUIRE(result == nullptr);
        }
    }
    SECTION("range search")
    {
        for (int i=0; i<100; ++i) {
            testData[i] = i;
            btree.insert(i, &testData[i]);
        }
        auto rs = btree.search(50, 99);
        REQUIRE(rs.to_ == 99);
        for (int i=50; i<=99; ++i) {
            auto result = static_cast<int*>(rs.data);
            REQUIRE(result != nullptr);
            REQUIRE(*result == i);
            ++rs;
        }
        REQUIRE(rs.data == nullptr); // 超出范围
        rs = btree.search(50, 150);
        REQUIRE(rs.to_ == 150);
        for (int i=50; i<100; ++i) {
            auto result = static_cast<int*>(rs.data);
            REQUIRE(result != nullptr);
            REQUIRE(*result == i);
            ++rs;
        }
        REQUIRE(rs.data == nullptr); // 超出范围
    }
    SECTION("remove")
    {
        for (int i=0; i<100; ++i) {
            testData[i] = i;
            btree.insert(i, &testData[i]);
        }
        for (int i=0; i<25; ++i){
            btree.remove(i);
            for (int j=0; j<100; ++j) {
                if (j<=i)
                    REQUIRE(btree.search(j) == nullptr);
                else {
                    auto *result = static_cast<int*>(btree.search(j));
                    REQUIRE(result != nullptr);
                    REQUIRE(*result == j);
                }
            }
        }
        for (int i=75; i<100; ++i){
            btree.remove(i);
            for (int j=0; j<25; ++j) {
                REQUIRE(btree.search(j) == nullptr);
            }
            for (int j = 25; j < 75; ++j) {
                auto result = static_cast<int *>(btree.search(j));
                REQUIRE(result != nullptr);
                REQUIRE(*result == j);
            }
            for (int j=75; j<=i; ++j) {
                REQUIRE(btree.search(j) == nullptr);
            }
        }
    }
}
